
#if	!defined( __20081117_DEF_LINUX_THREAD_H__ )
#define	__20081117_DEF_LINUX_THREAD_H__

#include	<assert.h>
#include	<pthread.h>

namespace PCE_Lib {
namespace CEnv_Def {
namespace PCE_Lib_CurrentCEnvironment {
namespace Tools {

class Thread
{
private:
	static void * sif_ThreadProc( void * param ) throw()
	{
		assert( NotNull( param ) );
		Thread	* p_this = ( Thread * )param;
		void	* ret_val;

		// synchronize between creator
		pthread_mutex_lock( &( p_this->m_StartLock ) );		// discard error
		pthread_mutex_unlock( &( p_this->m_StartLock ) );	// discard error
		// start routine
		assert( p_this->m_IsCreate );
		ret_val = p_this->Entry() ?
			reinterpret_cast< void * >( 1 ) : Null< void * >();

		p_this->m_IsCreate = false;
		return ret_val;
	}
protected:
	virtual bool Sleep( uint32_t usec ) throw()
	{
		pce_usleep( usec );
		return true;
	}
	virtual bool Entry( void ) throw() = 0;
public:
	virtual bool Start( void ) throw()
	{
		if( 0 != pthread_mutex_lock( & m_StartLock ) ) {
			return false;
		}
		if( m_IsCreate ) {
			pthread_mutex_unlock( & m_StartLock );
			return false;
		}
		if( 0 != ::pthread_create( const_cast< pthread_t * >( & m_Handle ),
				Null< pthread_attr_t * >(), sif_ThreadProc, this ) )
		{
			pthread_mutex_unlock( & m_StartLock );
			return false;
		}
		m_IsCreate = true;
		pthread_mutex_unlock( & m_StartLock );	// after this call, new thread begin to run
		return true;
	}
	virtual bool IsLive( bool & is_live ) throw()
	{
		is_live = true;
		if( 0 != pthread_mutex_lock( & m_StartLock ) ) {
			return false;
		}
		is_live = m_IsCreate;
		pthread_mutex_unlock( & m_StartLock );
		return true;
	}
	virtual bool Stop( void ) throw()
	{
		pthread_t	tmp = m_Handle;		// must read m_Handle first
		if( ! m_IsCreate ) {
			return false;
		}
		// synchronize between creator & thread
		pthread_mutex_lock( &( p_this->m_StartLock ) );		// discard error
		if( 0 != ::pthread_cancel( tmp ) ) {
			return false;
		}
		pthread_mutex_unlock( &( p_this->m_StartLock ) );	// discard error
		m_IsCreate = false;
		return true;
	}
	virtual bool Join( void ) throw()
	{
		pthread_t	tmp = m_Handle;		// must read m_Handle first
		if( ! m_IsCreate ) {
			return false;
		}
		return 0 ==::pthread_join( tmp, Null< void ** >() );
	}
protected:
	Thread( void ) throw()
		: m_IsCreate( false ), m_Handle(), m_StartLock()
	{
		pthread_mutex_init( & m_StartLock,
			Null< const pthread_mutexattr_t * >() );
	}
public:
	virtual ~Thread( void ) throw()
	{
		pthread_t	tmp = m_Handle;		// must read m_Handle first
		if( m_IsCreate ) {
			pthread_join( tmp, Null< void ** >() );	// join, discard error
		}
		pthread_mutex_destroy( & m_StartLock );	// discard error
	}
private:
	volatile bool		m_IsCreate;
	volatile pthread_t	m_Handle;
	pthread_mutex_t		m_StartLock;
};

}	// Tools
}	// PCE_Lib_CurrentCEnvironment
}	// CEnv_Def
}	// PCE_Lib

#endif	// __20081117_DEF_LINUX_THREAD_H__
